/*
 * Copyright 2012, pline.co.jp
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package jp.co.pline.android.wakeonlan;

import java.net.InetAddress;
import java.net.DatagramPacket;
import java.net.DatagramSocket;

import android.os.Bundle;
import android.content.Intent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.TextView;
import android.widget.Button;
import android.widget.Toast;

public class WakeOnLan extends android.app.Activity{
    private static final int MENU_SETTING=Menu.FIRST;

    public static final int PORT=9;
    private static final int MAC_ADDRESS_BYTES_LENGTH=6;

    String mMacaddrString=null;
    String mBroadcastaddrString=null;
    TextView mMacaddrTextView=null;
    TextView mBroadcastaddrTextView=null;
    Button mExecuteButton=null;

    private static byte[] getMacAddressBytes(String macAddressString)throws java.lang.IllegalArgumentException{
        byte[] bytes=new byte[MAC_ADDRESS_BYTES_LENGTH];
        String[] hexStrings=macAddressString.split("(\\:|\\-)");
        if(MAC_ADDRESS_BYTES_LENGTH!=hexStrings.length){
            throw new java.lang.IllegalArgumentException(macAddressString+": Invalid MAC address.");
        }
        try{
            for(int iii=0;MAC_ADDRESS_BYTES_LENGTH>iii;iii++){
                bytes[iii]=(byte)Integer.parseInt(hexStrings[iii],16);
            }
        }catch(java.lang.NumberFormatException exception){
            throw new java.lang.IllegalArgumentException(macAddressString+": Invalid hex digit in MAC address.");
        }
        return bytes;
    }

    public static byte[] generatePacketBytes(byte[] macAddressBytes){
	byte[] packetBytes=new byte[MAC_ADDRESS_BYTES_LENGTH+16*macAddressBytes.length];
	int index=0;
	for(;MAC_ADDRESS_BYTES_LENGTH>index;index++){
	    packetBytes[index]=(byte)0xff;
	}
	for(;packetBytes.length>index;index+=macAddressBytes.length){
	    System.arraycopy(macAddressBytes,0,packetBytes,index,macAddressBytes.length);
	}
	return packetBytes;
    }

    public static boolean sendPacket(byte[] packetBytes,String broadcastIpAddressString){
	DatagramSocket datagramSocket=null;
        try{
	    datagramSocket=new DatagramSocket();
        }catch(java.net.SocketException exception){
            System.err.println(exception.toString());
            return false;
        }
        try{
            datagramSocket.send(new DatagramPacket(packetBytes,packetBytes.length,InetAddress.getByName(broadcastIpAddressString),PORT));

	    return true;
        }catch(java.net.UnknownHostException exception){
            System.err.println(exception.toString());
        }catch(java.io.IOException exception){
            System.err.println(exception.toString());
        }finally{
	    datagramSocket.close();
        }
	return false;
    }

    public static boolean wakeOnLan(String macAddressString,String broadcastIpAddressString){
	byte[] macAddressBytes=null;
        try{
            macAddressBytes=getMacAddressBytes(macAddressString);
        }catch(java.lang.IllegalArgumentException exception){
            System.err.println(exception.toString());
            return false;
	}

	return sendPacket(generatePacketBytes(macAddressBytes),broadcastIpAddressString);
    }

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

	mMacaddrTextView=(TextView)findViewById(R.id.macaddr);
	mBroadcastaddrTextView=(TextView)findViewById(R.id.broadcastaddr);
	mExecuteButton=(Button)findViewById(R.id.execute);
	mExecuteButton.setOnClickListener(new View.OnClickListener(){
	    public void onClick(View view){
		if(!wakeOnLan(mMacaddrString,mBroadcastaddrString)){
		    Toast.makeText(WakeOnLan.this,"cannot send packet",Toast.LENGTH_LONG).show();
		}
		finish();
	    }
	});
    }

    public boolean onSettingMenuClick(MenuItem menuItem){
	final Intent intent=new Intent(WakeOnLan.this,Setting.class);
	startActivity(intent);
	return true;
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
	try {
	    return super.onCreateOptionsMenu(menu);
	} finally {
	    menu.add(0,MENU_SETTING,0,R.string.setting);
	}
    }

    @Override
    public boolean onMenuItemSelected(int featureId,MenuItem menuItem){
	return
		MENU_SETTING==menuItem.getItemId()?onSettingMenuClick(menuItem):
		super.onMenuItemSelected(featureId,menuItem);
    }

    @Override
    protected void onResume(){
	super.onResume();
	mMacaddrString=Setting.getMacaddr(this);
	mBroadcastaddrString=Setting.getBroadcastaddr(this);
	if(0<mMacaddrString.length()&&0<mBroadcastaddrString.length()){
	    mMacaddrTextView.setText(String.format("MAC address is %s",mMacaddrString));
	    mBroadcastaddrTextView.setText(String.format("broadcast IP address is %s",mBroadcastaddrString));
	    mExecuteButton.setClickable(true);
	}else{
	    mMacaddrTextView.setText(String.format("MAC address is %s","not setted"));
	    mBroadcastaddrTextView.setText(String.format("broadcast IP address is %s","not setted"));
	    mExecuteButton.setClickable(false);
	}
    }
}
